package com.gitee.srurl.core.api.impl.id;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ServiceLoaderUtil;
import cn.hutool.core.util.StrUtil;
import com.gitee.srurl.core.annotation.ApiImpl;
import com.gitee.srurl.core.api.IConfigCache;
import com.gitee.srurl.core.api.IUniqueIdGenerate;
import com.gitee.srurl.core.constant.ApiTypeConstant;
import com.gitee.srurl.core.exception.ServiceException;
import com.gitee.srurl.core.properties.OidProperties;
import com.gitee.srurl.oid.domain.OidData;
import com.gitee.srurl.oid.gen.Oid;
import com.gitee.srurl.oid.store.IOidStore;
import lombok.extern.slf4j.Slf4j;

import java.util.List;
import java.util.Optional;

/**
 * oid（order id）不需要上报
 * 因为数据的获取需要写入文件
 * 因此configCache目前也不需要 后期可以根据这个比如使用zk监听去实时改变批量数量等
 * 目前没做这个 为了以后扩展也和sid他们一样多一个构造方法
 * 因为这个其实需求不大 因为参数改动不会频繁 要调整改下配置文件 重启下项目
 *
 * @author zxw
 * @date 2023/5/8 21:51
 */
@Slf4j
@ApiImpl(ApiTypeConstant.UniqueIdGenerate.OID)
public class OidGenerate implements IUniqueIdGenerate {

    private final Oid oid;

    public OidGenerate(Oid oid) {
        this.oid = oid;
    }

    public OidGenerate(List<IConfigCache> configCacheList, OidProperties oidProperties) {

        if (oidProperties == null) {
            log.error("初始化oid参数不能为空！");
            throw new IllegalArgumentException("初始化id生成器ID参数不能为空！");
        }

        long workerId = Optional.ofNullable(oidProperties.getWorkerId()).orElse(0L);
        boolean useBatch = Optional.ofNullable(oidProperties.getUseBatch()).orElse(false);
        Integer batchNum = Optional.ofNullable(oidProperties.getBatchNum()).orElse(0);
        String storeType = oidProperties.getStoreType();
        storeType = StrUtil.isBlank(storeType) ? "file" : storeType;
        IOidStore oidStore = this.getStore(storeType);

        OidData oidData = OidData.builder()
                .workerId(workerId)
                .useBatch(useBatch)
                .batchNum(batchNum)
                .oidStore(oidStore)
                .build();

        oid = new Oid(oidData);
    }

    private IOidStore getStore(String storeType) {

        List<IOidStore> oidStoreList = ServiceLoaderUtil.loadList(IOidStore.class);
        if (CollectionUtil.isEmpty(oidStoreList)) {
            log.error("oid存储实现为空.");
            throw new ServiceException("oid存储实现不能为空！");
        }

        for (IOidStore oidStore : oidStoreList) {
            if (StrUtil.equals(oidStore.type(), storeType)) {
                return oidStore;
            }
        }

        log.error("oid存储类型:{},获取失败！", storeType);
        throw new ServiceException("oid存储获取失败！");
    }

    @Override
    public long getId() {
        return oid.nextId();
    }
}
